/**
 @fileOverview SFAガジェット Javascriptファイル
 @name gadget.js
 @author Akira Suzuki
 @version 1.0
*/

/* ----- グローバル変数 ---- */

/**
 * GDataオブジェクト
 * @type {google.gdata.calendar.CalendarService}
 */
var g_sfaGadget = null;

/**
 * ユーザのGmailアドレス
 * @type {string}
 */
var g_mailAddress = '';

/**
 * SFAID格納変数
 * @type {gadgets.Prefs}
 */
var g_userPrefs = new gadgets.Prefs();

/**
 * ログインを実行した関数
 * @type {string}
 */
var g_callLoginFunc = '';

/**
 * SFA活動ID
 * @type {string}
 */
var g_callID = '';

/**
 * 再ログイン回数
 * @type {number}
 */
var g_retryLoginCount = 0;

/**
 * 現在のガジェットの状態
 * @type {string}
 */
var g_nowState = '';

/**
 * SFAガジェットのバージョン
 * @type {number}
 */
var g_thisVersion = '1';

/* ----- // グローバル変数 ----- */

/**
 * 画面を切り替える
 * @param {string} id 切り替える画面のdiv要素id名
 * @type void
 */
function showOnly(id) {
	var sections = ['main', 'comment', 'approval', 'iniloading','loading', 'SFALogin', 'setting', 'version', 'reload'];
	for (var i = 0, section; section = sections[i]; ++i) {
		$('#' + section).get(0).style.display = section === id ? 'block' : 'none';
	}
	
    resetMessage();                         // メッセージ部分を初期化
	gadgets.window.adjustHeight();			// 動的にガジェットの高さを変更
}


/**
 * google.calendar.getPreferencesのコールバック関数<br>
 * GoogleログインユーザのGmailアドレス取得
 * @param {Object} prefs UserPreferencesオブジェクト
 * @type callback
 */
function preferencesCallback(prefs) {
	g_mailAddress = prefs.viewer;		// カレンダー表示者のGmailアドレス
}


/**
 * カレンダーイベントハンドラ設定
 * @type void
 */
function setHandler() {
	google.calendar.read.subscribeToEvents(eventsCallback);		// カレンダーの予定を選択したらeventsCallback関数実行
	//google.calendar.subscribeToDates(datesCallback);			// カレンダーの日付表示範囲を変更したらdetesCallback関数実行
}


/**
 * GDataAPIエラーコールバック関数
 * @param {Object} e エラーオブジェクト
 * @type callback
 */
var handleError = function(e) {
	if(e.message == "403 Error") {
		console.debug(e);
		showMessage('error', "Google認証に失敗しました。");
		location.reload();						// ガジェットをリロード
	}
	else {
		console.debug(e);
		showOnly('reload');
		showMessage('error', "Googleとの通信に失敗しました。");
	}
}


/**
 * OAuth認証取得関数
 * @type void
 */
function getAuth(){
	
	// OAuth認証ポップアップ表示
	var callback = function(response) {

		if(response.oauthApprovalUrl) {
			// 認証ポップアップの設定
			var popup = shindig.oauth.popup({
				destination: response.oauthApprovalUrl,
				windowOptions: 'height=600,width=800',
				onOpen: function() {
					showOnly('loading');
				},
				onClose: function() {
					showOnly('loading');
					getAuth();
				}
			});
			
			// 認証ポップアップ表示
			$('#personalize').get(0).onclick = popup.createOpenerOnClick();
			showOnly('approval');
		}
		else if(response.feed) {
			setHandler();		// 認証を取得したらイベントハンドラ設定関数へ
			showOnly('main');
		}
		else {
			showMessage('error', 'Something went wrong');
		    
		}
	};
	
	// とりあえず適当なクエリを投げて認証を取得
	var feedUri = 'https://www.google.com/calendar/feeds/default/private/full';
	var query = new google.gdata.calendar.CalendarEventQuery(feedUri);
	query.setSingleEvents(true);	// シングルイベント(普通のイベント)を取得
	query.setMaxResults(1);			// 1件取得
	
	g_sfaGadget.getEventsFeed(query, callback, handleError);	// 取得実行
}


/**
 * GData APIで取得したイベントとサイドバーガジェットAPIで取得したイベントを比較し、SFA活動を検索する
 * @param {google.gdata.calendar.CalendarFeed} result GData APIで取得したイベントデータ
 * @param {calendar.event} event サイドバーガジェットAPIで取得したイベントデータ
 * @type void
 */
function getResults(result, event) {
	var entries = result.feed.entry;	// イベント配列取得
	var selectedEntry = null;			// 選択されている（詳細ビューが表示されている）予定
	var when = setDateFromEventDate(event);
	
	
	// 選択されている予定を探す
	for(var i = 0, len = entries.length; i < len; i++) {
		var entry = entries[i];		// イベントをイベント配列から取得
		var gdTime = entry.getTimes(); 
		var gdStartTime = gdTime[0].startTime;
		var gdEndTime = gdTime[0].endTime;
	    
		if( when[0] == gdStartTime
			&& when[1] == gdEndTime
			&& event.title == entry.getTitle().getText() 
			&& event.details == entry.getContent().getText() 
		  ) {
			  selectedEntry = entry;
			  break;
		  }
	}
	
	if(selectedEntry != null) {
		var extProps = selectedEntry.getExtendedProperties();		// イベントに付与されているExtendedPropertyの配列を取得
		var is_SFAevent = false;
		for(var j = 0, len2 = extProps.length; j < len2; j++) {
			var extProp = extProps[j];
			
			// もしイベントがSFA活動だったら
			if(g_nowState == 'comment' && extProp.getName() == 'sugar_id') {
				g_callID = extProp.getValue();			// sugar_id取得
				is_SFAevent = true;
				// getComments();						// コメント取得
				$('#commentData').val('このSFA活動を確認しました。');
				
				if(g_nowState == 'comment') showOnly('comment');
				break;
			}
		}
		
		// SFA活動以外ならメイン画面へ
		if(!is_SFAevent) {
			g_nowState = 'main';
			showOnly('main');
		}
	}
	else {
		showOnly('main');
	}
}


/**
 * GData取得処理
 * @param {calendar.event} event サイドバーガジェットAPIで取得したイベントデータ
 * @type void
 */
function fetchData(event) {
	// 予定の詳細を開いたときだけ処理をする
	if(event.details != null && event.details != undefined) {
		showOnly('loading');
		
		var callback = function(response) { 
			if (response.feed) {		
				getResults(response, event);
			} 
			else {
                showMessage('error', 'Something went wrong');
			}
		};
		
		// CalendarEventクエリ作成
		var feedUri = 'https://www.google.com/calendar/feeds/' + event.calendar.email + '/private/full/';
		var query = new google.gdata.calendar.CalendarEventQuery(feedUri);
		query.setSingleEvents(true);	// シングルイベント(普通のイベント)を取得
		query.setMaxResults(100);		// 最大項目数(100件まで)
		
		var when = setDateFromEventDate(event);

		var startTime = new google.gdata.DateTime.fromIso8601(when[0]);
		var endTime = new google.gdata.DateTime.fromIso8601(when[1]);
		
		query.setMinimumStartTime(startTime);	// 取得開始時刻
		query.setMaximumStartTime(endTime);		// 取得終了時刻

		g_sfaGadget.getEventsFeed(query, callback, handleError); // 取得実行
	}
}


/**
 * サイドバーガジェットAPIで取得したイベントデータから日付を取得
 * @param {calendar.event} event サイドバーガジェットAPIで取得したイベントデータ
 * @return Array
 * @type void
 */
function setDateFromEventDate(event) {
	// 取得時刻設定
	var sYear = event.startTime.year, sMonth = event.startTime.month, sDate = event.startTime.date,
	 sHour = event.startTime.hour, sMinute = event.startTime.minute, sSecond = event.startTime.second;
	var eYear = event.endTime.year, eMonth = event.endTime.month, eDate = event.endTime.date,
	 eHour = event.endTime.hour, eMinute = event.endTime.minute, eSecond = event.endTime.second;
	
	// 時間が終日だった場合、時間を設定
	if(event.allDay) {
		sHour = '00'; sMinute = '00'; sSecond = '00';
		eHour = '00'; eMinute = '00'; eSecond = '00';
	}
	else {
		// 月と日が一桁だった場合、0を加えて二桁にする
		if(sMonth < 10) sMonth = '0' + sMonth;
		if(sDate < 10) sDate = '0' + sDate;
		if(sHour < 10) sHour = '0' + sHour;
		if(sMinute < 10) sMinute = '0' + sMinute;
		if(sSecond < 10) sSecond = '0' + sSecond;
		if(eMonth < 10) eMonth = '0' + eMonth;
		if(eDate < 10) eDate = '0' + eDate;
		if(eHour < 10) eHour = '0' + eHour;
		if(eMinute < 10) eMinute = '0' + eMinute;
		if(eSecond < 10) eSecond = '0' + eSecond;
	}
	
	var when = new Array(2) ;
	when[0] = sYear+'-'+sMonth+'-'+sDate+'T'+sHour+':'+sMinute+':'+sSecond+'.000+09:00';
	when[1] = eYear+'-'+eMonth+'-'+eDate+'T'+eHour+':'+eMinute+':'+eSecond+'.000+09:00';
	
	// 開始時間と終了時間が同じ場合には終了時間を開始時間+1mにする
	if(when[0] == when[1]) {
		when[1] = new google.gdata.DateTime.fromIso8601(eYear+'-'+eMonth+'-'+eDate+'T'+eHour+':'+(eMinute+1)+':'+eSecond+'.000+09:00');
	}
	
	return when;
}


/**
 * google.calendar.read.subscribeToEventsのコールバック関数<br>
 * カレンダー上のイベントを選択 または 解除したときにコールされる
 * @param {calendar.event} event サイドバーガジェットAPIで取得したイベントデータ
 * @type callback
 */
function eventsCallback(event) {
	if(event == null) {
		g_callID = '';
		g_nowState = 'main';	// 状態変更
		showOnly('main');
	}
	else {
		g_nowState = 'comment';	// 状態変更
		fetchData(event);
	}

    //メッセージ部分を初期化
    //            resetMessage();
}


/**
 * SFAログインAjax通信コールバック関数<br>
 * SFAログイン成功時、SFA IDを保持
 * @param {json} data SFAからのレスポンスデータ
 * @param {string} dataType データ形式
 * @type callback
 */
var setUserID = function(data, dataType) {
	var callFunc = g_callLoginFunc;
	g_callLoginFunc = '';
	

	if(data.status == 'success') {
		// ログインに成功しているのに再ログインの要求がきたらCookie有効の設定を促す
		if(g_retryLoginCount < 1) {
			switch(callFunc) {
				case '':
					g_retryLoginCount = 0;
					showOnly('loading');
					g_userPrefs.set('SFAUserID', $('#SFAID').val()); 	// ユーザID保持
					getAuth();											// OAuth認証処理へ
					break;
		
				// 以下の2つのケースはセッション切れのとき
				case 'sendComment':
					g_retryLoginCount++;
					sendComment();		// ログインに成功したら再度リクエスト送信
					break;
		
				case 'getComments':
					g_retryLoginCount;
					getComments();		// ログインに成功したら再度リクエスト送信
					break;
			}
		}
		else {
			alert('Cookieの設定が正しくありません。\nブラウザのCookie設定が有効（全て許可）になっているか確認してください。');
		}
	}
	else if(data.status == 'error') {
		switch(data.code) {
			// code 3: ユーザ名とパスワードの組み合わせが正しくない
			case 3:
				showOnly('SFALogin');
				showMessage('error', 'ユーザIDが正しくありません。\n');
				break;
		
			default:
				showMessage('error', 'ログインに失敗しました。\n');
				break;
		}
	}
}


/**
 * SFAコメント送信Ajax通信コールバック関数<br>
 * コメント送信リクエストがSFAに届いた場合、コールされる
 * @param {json} data SFAからのレスポンスデータ
 * @param {string} dataType データ形式
 * @type callback
 */
var getPostStatus = function(data, dataType) {

	// 現在の状態がcommentなら
	if(g_nowState == 'comment') {
		if(data.status == 'success') {
			showMessage('ok', 'コメント送信成功');
			$('#commentData').val('');	// テキストエリアをクリア
		}
		else if(data.status == 'error') {
			switch(data.code) {
				// code 1: セッション切れのとき再ログイン
				case 1:
					g_callLoginFunc = 'sendComment';
					sendLogin();
					break;
			
				default:
					break;
			}
		}
	}
	else {
		g_retryLoginCount = 0;
	}
}


/**
 * SFAコメント受信Ajax通信コールバック関数<br>
 * コメント受信リクエストがSFAに届いた場合、コールされる
 * @param {json} data SFAからのレスポンスデータ
 * @param {string} dataType データ形式
 * @type callback
 */
var viewComments = function(data, dataType) {
	if(data.status == 'success') {
		var str ='';
		var comments = data.Comments;

		for(var i = 0, len = comments.length; i < len; i++) {
			var comment = comments[i];
			str += "<p><font color='#0000ff'>"
				+comment.created_by_name+" "+comment.date_entered
				+"</font><p>"
				+"<p>"+comment.description+"</p>";
		}
		$('#commentList').html(str);
        /*				
		 // 予定詳細画面を開いている時にコメント画面を表示
		 if(g_isEvent) {
		 $('#commentData').val('このSFA活動を確認しました。');
		 showOnly('comment');
		 }
		 else {
		 showOnly('main');
		 }
         */
	}
	else if(data.status == 'error') {
		switch(data.code) {
			// code 1: セッション切れのとき再ログイン
		case 1:
			g_callLoginFunc = 'getComments';
			sendLogin();
			break;
			
		default:
			showMessage('error', 'コメントデータ取得失敗');
			break;
		}
	}
}


/**
 * SFAログインリクエスト送信
 * @type void
 */
function sendLogin() {
	var mailAddress = g_mailAddress;
	var userID = '';
	if(g_userPrefs.getString('SFAUserID') == '') {
		userID = $('#SFAID').val();
	}
	else {
		userID = g_userPrefs.getString('SFAUserID');
	}

	$.ajax({
		type: 'GET',
		url: 'https://sfadev.jtoa/sugarcrm/index.php',						// リクエストURL
		data: {																// 送信データ
			'google_gadget_call': 'true',
			'module': 'Users',
			'action': 'Authenticate',
			'user_name': userID,
			'email': mailAddress,
			'hash': MD5_hexhash(userID + mailAddress + 'SFA-HAMBURGER'),
		},
		dataType: 'jsonp',													// 返り値のデータ型:jsonp
		jsonp: 'callback',													// コールバック
		cache: false,														// キャッシュ無効
		success: setUserID,													// 成功時コールバック、setUserID関数へ
		error: function(XMLHttpRequest, textStatus, errorThrown) {			// 失敗時コールバック
			showMessage('error', 'Error!SFAサーバが停止している可能性があります。');
			console.debug( 'xhr:', XMLHttpRequest, 'status', textStatus, 'errorThrown', errorThrown);
		}
	});
}


/**
 * SFAからコメントデータを取得する
 * @type void
 */
function getComments() {
	$.ajax({
		type: 'GET',
		url: 'https://sfadev.jtoa/sugarcrm/index.php',						// リクエストURL
		data: {																// 送信データ
			'google_gadget_call': 'true',
			'module': 'Comments',
			'action': 'Listview',
			'parent_type': 'Calls',
			'parent_id': g_callID,
		},
		dataType: 'jsonp',													// 返り値のデータ型:jsonp
		jsonp: 'callback',													// コールバック
		cache: false,														// キャッシュ無効
		success: viewComments,												// 成功時コールバック、viewList関数へ
		error: function(XMLHttpRequest, textStatus, errorThrown) {			// 成功時コールバック
			showMessage('error', 'Error!SFAサーバが停止している可能性があります。');
			console.debug( 'xhr:', XMLHttpRequest, 'status', textStatus, 'errorThrown', errorThrown);
		}
	});
}


/**
 * SFAにコメントデータを送信する
 * @type void
 */
function sendComment() {
    
    if($('#commentData').val() == ''){
        showMessage('error', 'コメントを入力して下さい');
    }else{
    
	    $.ajax({
		    type: 'GET',
		    url: 'https://sfadev.jtoa/sugarcrm/index.php',						// リクエストURL
		    data: {																// 送信データ
			    'google_gadget_call': 'true',
			    'module': 'Comments',
			    'action': 'Save',
			    'relate_to': 'Calls',
			    'relate_id': g_callID,
			    'assigned_user_id': g_userPrefs.getString('SFAUserID'),
			    'description': $('#commentData').val(),
		    },
		    dataType: 'jsonp',													// 返り値のデータ型:jsonp
		    jsonp: 'callback',													// コールバック
		    cache: false,														// キャッシュ無効
		    success: getPostStatus,												// 成功時コールバック、getPostStatus関数へ
		    error: function(XMLHttpRequest, textStatus, errorThrown) {			// 失敗時コールバック
                showMessage('error', 'Error!SFAサーバが停止している可能性があります。');
			    console.debug( 'xhr:', XMLHttpRequest, 'status', textStatus, 'errorThrown', errorThrown);
		    }
	    });
    }

}


/**
 * バージョンチェック
 * @type void
 */
var checkVersion = function(){
    
    var version = 'Ver. '+g_thisVersion;
    var new_version = 'Ver. '+g_config['version'];
    // config.js と g_thisVersionで バージョンチェック
    if(parseInt(g_config['version']) > parseInt(g_thisVersion) ){
        var url =  'https://www.google.com/calendar/render?gadgeturl='+g_config['url'];
        $('span.version').text(version);
        $('span.new_version').text(new_version);
        $('#update_version').attr('href', url);
        $('#version .update').show();
        showOnly('version');
    }else{
  
        $('span.version').text(version);
        $('#version .no_update').show();
        showOnly('version');    
    }

};



/**
 * エラーおよびOKメッセージを表示する  
 * @param {string} type メッセージタイプ。"ok" | "error"
 * @param {string} mes メッセージ
 * type void
 */
var showMessage = function(type, mes){
    
    // 初期化
    resetMessage();
    
    // メッセージを表示
    if(type == "ok" || type == "error"){
        $('.'+type, '#message')
            .text(mes)
            .show("fast", function(){
                // 動的にgadgetの高さを変更
                gadgets.window.adjustHeight();
            });
    }
};



/**
 * 表示しているメッセージを削除して初期化
 * @type void
 **/
var resetMessage = function(){
    
    // 初期化
    $("div", '#message').each(function(){
        $(this).text("").hide();
    });
};


$(document).ready(function() {
	/**
	 *	・ID送信ボタンを押したときに実行
	 **/
	$('#loginForm').submit(function() {
		sendLogin();
	});
	
	/**
	 *	・コメント送信ボタンを押したときに実行
	 **/
	$('#commentSend').submit(function() {
		sendComment();
	});

	/**
	 *	・バージョンを確認
	 **/
	$('#check_version').click(function(event) {
        event.preventDefault();
		checkVersion();
	});

    // バージョン確認画面へ
	$('.go_setting').click(function(event) {
        event.preventDefault();
		showOnly('setting');
	});

    // バージョン確認画面からメイン画面へ戻る
	$('.go_main').click(function(event) {
        event.preventDefault();
		showOnly('main');
	});

});



/**
 * ガジェットロード時にコールされる
 * @param {Funtion} function() SFAガジェットの初期状態をコントロールする
 * @type callback
 */
gadgets.util.registerOnLoadHandler(function() {
	showOnly('iniloading');
	g_sfaGadget = new google.gdata.calendar.CalendarService('SFA-Gadget');	// GDataオブジェクト作成
	g_sfaGadget.useOAuth('google');											// OAuth認証を使用
	
	google.calendar.getPreferences(preferencesCallback);					// カレンダーユーザのGmailアドレス取得
	
	// ガジェットがSFA IDを保持してなければSFAログイン画面を出力
	// SFA IDを保持している場合は認証をパスしてガジェットを起動
	if(g_userPrefs.getString('SFAUserID') == '') {
		showOnly('SFALogin');										// ID入力画面表示
	}
	else {
		getAuth();													// OAuth認証処理へ
	}
});